{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ade42be5-7813-4aa6-9f4f-aad4318d4175",
   "metadata": {},
   "source": [
    "# Document Summary Index\n",
    "\n",
    "This demo showcases the document summary index, over Wikipedia articles on different cities.\n",
    "\n",
    "The document summary index will extract a summary from each document and store that summary, as well as all nodes corresponding to the document.\n",
    "\n",
    "Retrieval can be performed through the LLM or embeddings (which is a TODO). We first select the relevant documents to the query based on their summaries. All retrieved nodes corresponding to the selected documents are retrieved."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5e03a80b-6f5e-4dda-9a05-201d4fafede1",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import logging\n",
    "import sys\n",
    "\n",
    "logging.basicConfig(stream=sys.stdout, level=logging.INFO)\n",
    "logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))\n",
    "# # Uncomment if you want to temporarily disable logger\n",
    "# logger = logging.getLogger()\n",
    "# logger.disabled = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4b6d4d55-2a2f-41d5-aa32-159d6bc406fe",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import nest_asyncio\n",
    "\n",
    "nest_asyncio.apply()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4fb7288e-22f8-4753-a6ea-197cf2f8aba5",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:numexpr.utils:Note: NumExpr detected 12 cores but \"NUMEXPR_MAX_THREADS\" not set, so enforcing safe limit of 8.\n",
      "Note: NumExpr detected 12 cores but \"NUMEXPR_MAX_THREADS\" not set, so enforcing safe limit of 8.\n",
      "INFO:numexpr.utils:NumExpr defaulting to 8 threads.\n",
      "NumExpr defaulting to 8 threads.\n"
     ]
    }
   ],
   "source": [
    "from llama_index import (\n",
    "    SimpleDirectoryReader,\n",
    "    LLMPredictor,\n",
    "    ServiceContext,\n",
    "    get_response_synthesizer,\n",
    ")\n",
    "from llama_index.indices.document_summary import DocumentSummaryIndex\n",
    "from llama_index.llms import OpenAI"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8c391a70-7690-4bbd-a2dc-f95b845991a7",
   "metadata": {
    "tags": []
   },
   "source": [
    "### Load Datasets\n",
    "\n",
    "Load Wikipedia pages on different cities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "23ae10cc-f552-434c-9133-e4adf6642198",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "wiki_titles = [\"Toronto\", \"Seattle\", \"Chicago\", \"Boston\", \"Houston\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "24e0e454-218e-4937-b1f9-f1c8e2abba43",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "\n",
    "import requests\n",
    "\n",
    "for title in wiki_titles:\n",
    "    response = requests.get(\n",
    "        \"https://en.wikipedia.org/w/api.php\",\n",
    "        params={\n",
    "            \"action\": \"query\",\n",
    "            \"format\": \"json\",\n",
    "            \"titles\": title,\n",
    "            \"prop\": \"extracts\",\n",
    "            # 'exintro': True,\n",
    "            \"explaintext\": True,\n",
    "        },\n",
    "    ).json()\n",
    "    page = next(iter(response[\"query\"][\"pages\"].values()))\n",
    "    wiki_text = page[\"extract\"]\n",
    "\n",
    "    data_path = Path(\"data\")\n",
    "    if not data_path.exists():\n",
    "        Path.mkdir(data_path)\n",
    "\n",
    "    with open(data_path / f\"{title}.txt\", \"w\") as fp:\n",
    "        fp.write(wiki_text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6f765eee-0c80-476c-b1f2-b96b5dd176db",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Load all wiki documents\n",
    "city_docs = []\n",
    "for wiki_title in wiki_titles:\n",
    "    docs = SimpleDirectoryReader(input_files=[f\"data/{wiki_title}.txt\"]).load_data()\n",
    "    docs[0].doc_id = wiki_title\n",
    "    city_docs.extend(docs)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ef3de855-a3ee-4994-b3c0-0099fa7b5704",
   "metadata": {},
   "source": [
    "### Build Document Summary Index\n",
    "\n",
    "We show two ways of building the index:\n",
    "- default mode of building the document summary index\n",
    "- customizing the summary query\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e4da51df-ff9f-4141-91fe-719e00824328",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# # LLM Predictor (gpt-3.5-turbo)\n",
    "chatgpt = OpenAI(temperature=0, model=\"gpt-3.5-turbo\")\n",
    "service_context = ServiceContext.from_defaults(llm=chatgpt, chunk_size=1024)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93c531c9-4aee-47ae-a4d2-81af3a6af908",
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# default mode of building the index\n",
    "response_synthesizer = get_response_synthesizer(\n",
    "    response_mode=\"tree_summarize\", use_async=True\n",
    ")\n",
    "doc_summary_index = DocumentSummaryIndex.from_documents(\n",
    "    city_docs,\n",
    "    service_context=service_context,\n",
    "    response_synthesizer=response_synthesizer,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf5d19a2-5fa3-4f1b-aadd-25c209cfeb75",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\nThis document provides an overview of the history and geography of Boston, Massachusetts, from its founding in the 17th century to the present day. It covers topics such as the city's population growth, immigration, land reclamation, development, gentrification, climate, landmarks, neighborhoods, transportation, demographics, economy, education system, higher education, public safety, environment, sports, parks and recreation, government and politics, media, film, video game, and infrastructure. It can answer questions about the founding of Boston, its role in the American Revolution and War of 1812, its population growth, immigration, land reclamation, development, gentrification, climate, landmarks, neighborhoods, transportation, demographics, economy, education system, higher education, public safety, environment, sports, parks and recreation, government and politics, media, film, video game, and infrastructure.\""
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "doc_summary_index.get_document_summary(\"Boston\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "349c2872-2b53-4812-9392-b89e5879e32a",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "doc_summary_index.storage_context.persist(\"index\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f96e6524-f8ab-4227-ad5a-3dcb3b640532",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:llama_index.indices.loading:Loading all indices.\n",
      "Loading all indices.\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "from llama_index.indices.loading import load_index_from_storage\n",
    "from llama_index import StorageContext\n",
    "\n",
    "# rebuild storage context\n",
    "storage_context = StorageContext.from_defaults(persist_dir=\"index\")\n",
    "doc_summary_index = load_index_from_storage(storage_context)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0a486251-1ace-4112-8b7a-d5ce41f968ce",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# customizing the summary query\n",
    "summary_query = (\n",
    "    \"Give a concise summary of this document in bullet points. Also describe some of the questions \"\n",
    "    \"that this document can answer. \"\n",
    ")\n",
    "doc_summary_index = DocumentSummaryIndex.from_documents(summary_query=summary_query)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f76b3344-8e24-4e72-893b-7accd2a3fa57",
   "metadata": {},
   "source": [
    "### Perform Retrieval from Document Summary Index\n",
    "\n",
    "We show how to execute queries at a high-level. We also show how to perform retrieval at a lower-level so that you can view the parameters that are in place. We show both LLM-based retrieval and embedding-based retrieval using the document summaries."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3e3f65a3-482f-4481-9933-19ac55e91719",
   "metadata": {},
   "source": [
    "#### High-level Querying\n",
    "\n",
    "Note: this uses the default, LLM-based form of retrieval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "5e925b75-0a99-49cc-8e9a-daaf715ee490",
   "metadata": {},
   "outputs": [],
   "source": [
    "query_engine = doc_summary_index.as_query_engine(\n",
    "    response_mode=\"tree_summarize\", use_async=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c190a1e7-b85c-41cd-af42-e2521d2406a9",
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [],
   "source": [
    "response = query_engine.query(\"What are the sports teams in Toronto?\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fc5b99c2-06de-4071-9314-eec75c50c5f5",
   "metadata": {},
   "source": [
    "#### LLM-based Retrieval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "afd99ce8-8347-4e6e-88e4-23dd8fcb9084",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from llama_index.indices.document_summary import DocumentSummaryIndexRetriever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "67e397dd-fbb0-4465-994a-7527b3a6dd57",
   "metadata": {},
   "outputs": [],
   "source": [
    "retriever = DocumentSummaryIndexRetriever(\n",
    "    doc_summary_index,\n",
    "    # choice_select_prompt=choice_select_prompt,\n",
    "    # choice_batch_size=choice_batch_size,\n",
    "    # format_node_batch_fn=format_node_batch_fn,\n",
    "    # parse_choice_select_answer_fn=parse_choice_select_answer_fn,\n",
    "    # service_context=service_context\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "eef31654-27ea-4fb0-b29e-b18e5bf867f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "retrieved_nodes = retriever.retrieve(\"What are the sports teams in Toronto?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "96f76e79-1595-43b3-81e7-9ca7547fa2d1",
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8.0\n",
      "Toronto ( (listen) tə-RON-toh; locally [təˈɹɒɾ̃ə] or [ˈtɹɒɾ̃ə]) is the capital city of the Canadian province of Ontario. With a recorded population of 2,794,356 in 2021, it is the most populous city in Canada and the fourth most populous city in North America. The city is the anchor of the Golden Horseshoe, an urban agglomeration of 9,765,188 people (as of 2021) surrounding the western end of Lake Ontario, while the Greater Toronto Area proper had a 2021 population of 6,712,341. Toronto is an international centre of business, finance, arts, sports and culture, and is recognized as one of the most multicultural and cosmopolitan cities in the world.Indigenous peoples have travelled through and inhabited the Toronto area, located on a broad sloping plateau interspersed with rivers, deep ravines, and urban forest, for more than 10,000 years. After the broadly disputed Toronto Purchase, when the Mississauga surrendered the area to the British Crown, the British established the town of York in 1793 and later designated it as the capital of Upper Canada. During the War of 1812, the town was the site of the Battle of York and suffered heavy damage by American troops. York was renamed and incorporated in 1834 as the city of Toronto. It was designated as the capital of the province of Ontario in 1867 during Canadian Confederation. The city proper has since expanded past its original limits through both annexation and amalgamation to its current area of 630.2 km2 (243.3 sq mi).\n",
      "The diverse population of Toronto reflects its current and historical role as an important destination for immigrants to Canada. More than half of residents were born outside of Canada, more than half of residents belong to a visible minority group, and over 200 distinct ethnic origins are represented among its inhabitants. While the majority of Torontonians speak English as their primary language, over 160 languages are spoken in the city. The mayor of Toronto is elected by direct popular vote to serve as the chief executive of the city. The Toronto City Council is a unicameral legislative body, comprising 25 councillors since the 2018 municipal election, representing geographical wards throughout the city.Toronto is a prominent centre for music, theatre, motion picture production, and television production, and is home to the headquarters of Canada's major national broadcast networks and media outlets. Its varied cultural institutions, which include numerous museums and galleries, festivals and public events, entertainment districts, national historic sites, and sports activities, attract over 43 million tourists each year. Toronto is known for its many skyscrapers and high-rise buildings, in particular the tallest free-standing structure on land outside of Asia, the CN Tower.The city is home to the Toronto Stock Exchange, the headquarters of Canada's five largest banks, and the headquarters of many large Canadian and multinational corporations. Its economy is highly diversified with strengths in technology, design, financial services, life sciences, education, arts, fashion, aerospace, environmental innovation, food services, and tourism. Toronto is the third-largest tech hub in North America after Silicon Valley and New York City, and the fastest growing.\n",
      "\n",
      "\n",
      "== Etymology ==\n",
      "\n",
      "The word Toronto was recorded with various spellings in French and English, including Tarento, Tarontha, Taronto, Toranto, Torento, Toronto, and Toronton. Taronto referred to \"The Narrows\", a channel of water through which Lake Simcoe discharges into Lake Couchiching where the Huron had planted tree saplings to corral fish. This narrows was called tkaronto by the Mohawk, meaning \"where there are trees standing in the water,\" and was recorded as early as 1615 by Samuel de Champlain.\n",
      "The word \"Toronto\", meaning \"plenty\" also appears in a 1632 French lexicon of the Huron language, which is also an Iroquoian language. It also appears on French maps referring to various locations, including Georgian Bay, Lake Simcoe, and several rivers. A portage route from Lake Ontario to Lake Huron running through this point, known as the Toronto\n"
     ]
    }
   ],
   "source": [
    "print(retrieved_nodes[0].score)\n",
    "print(retrieved_nodes[0].node.get_text())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a215ef33-5d05-42ad-83c5-409ccc288d26",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# use retriever as part of a query engine\n",
    "from llama_index.query_engine import RetrieverQueryEngine\n",
    "\n",
    "# configure response synthesizer\n",
    "response_synthesizer = get_response_synthesizer()\n",
    "\n",
    "# assemble query engine\n",
    "query_engine = RetrieverQueryEngine(\n",
    "    retriever=retriever,\n",
    "    response_synthesizer=response_synthesizer,\n",
    ")\n",
    "\n",
    "# query\n",
    "response = query_engine.query(\"What are the sports teams in Toronto?\")\n",
    "print(response)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "bfb24cb8-b839-4754-b653-ac40cebfe0bc",
   "metadata": {},
   "source": [
    "#### Embedding-based Retrieval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bc47dc54-197f-43bb-9298-b2af24c6b095",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from llama_index.indices.document_summary import DocumentSummaryIndexEmbeddingRetriever"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0dcb81cb-0d36-4af8-a0c5-9061a2dce986",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "retriever = DocumentSummaryIndexEmbeddingRetriever(\n",
    "    doc_summary_index,\n",
    "    # choice_select_prompt=choice_select_prompt,\n",
    "    # choice_batch_size=choice_batch_size,\n",
    "    # format_node_batch_fn=format_node_batch_fn,\n",
    "    # parse_choice_select_answer_fn=parse_choice_select_answer_fn,\n",
    "    # service_context=service_context\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "48934544-3dde-4231-b41c-540139378751",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "retrieved_nodes = retriever.retrieve(\"What are the sports teams in Toronto?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "6f06e5f6-d62e-4348-8ef5-d4cb6219b54e",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(retrieved_nodes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb93c084-411b-40c2-b5d4-6fc2a90b8ecb",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
